#define _POSIX_C_SOURCE 200809L
#include <limits.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define MAXSTRINGSZ 4096

static pthread_key_t key;
static pthread_once_t init_done= PTHREAD_ONCE_INIT;
pthread_mutex_t env_mutex= PTHREAD_MUTEX_INITIALIZER;

extern char **environ;

static void thread_init(void) {
    pthread_key_create(&key, free);
}

char * _getenv(const char *name) {
    int i, len; 
    char *envbuf;
    pthread_once(&init_done, thread_init);
    pthread_mutex_lock(&env_mutex);

    len= strlen(name);
    if ((envbuf= (char *)pthread_getspecific(key)) == NULL) {
        envbuf= malloc(MAXSTRINGSZ * (sizeof(char)));
        if (envbuf == NULL) {
            pthread_mutex_unlock(&env_mutex);
            return (NULL);
        }
        pthread_setspecific(key, envbuf);
    }
    for (i=0; environ[i] != NULL; i++) {
        if (strncmp(name, environ[i], len) == 0 && environ[i][len] == '=') {
            strncpy(envbuf, environ[i]+ len+1, MAXSTRINGSZ-1);
            pthread_mutex_unlock(&env_mutex);
            return envbuf;
        }
    }
    pthread_mutex_unlock(&env_mutex);
    return(NULL);
}

void *thr_fn(void *env) {
    char *name= (char *)env;
    char *enval;

    _getenv(name);
    enval= (char *)pthread_getspecific(key);
    sleep(1);
    
    printf("%s=%s\n", name, enval);
    return((void *)enval);
}

int main(void) {
    pthread_t tid1, tid2, tid3;
    void *retval;
    char *env1= "abc";
    char *env2= "def";
    char *env3= "ghj";

    // char *val1, *val2, *val3;
    setenv(env1, "ABCVAL", 0);
    setenv(env2, "DEFVAL", 0);
    setenv(env3, "GHJVAL", 0);

    pthread_create(&tid1, NULL, thr_fn, (void *)env1);
    pthread_create(&tid2, NULL, thr_fn, (void *)env2);
    pthread_create(&tid3, NULL, thr_fn, (void *)env3);

    pthread_join(tid1, &retval);
    pthread_join(tid2, &retval);
    pthread_join(tid3, &retval);

    if (pthread_getspecific(key) == NULL) {
        printf("main thread key is NULL\n");
    }
    return(0);
}
